package estates.facade;

import estates.addon.*;
import estates.model.Estate;
import estates.model.User;
import estates.model.Comment;
import estates.util.ErrorCodes;
import javax.mail.*;
import javax.mail.internet.*;
import java.util.*;

public class Fasada1 {

    private List<Estate> katalogOfert = new ArrayList<Estate>();
    private List<User> katalogUsers = new ArrayList<User>();
    private List<Comment> komentarze = new ArrayList<Comment>();

    public Fasada1(List<Comment> c, List<Estate> e, List<User> u) {
        katalogOfert = e;
        katalogUsers = u;
        komentarze = c;
    }

    public Fasada1(){
        
    }

    private ArrayList<Estate> wyszukaj_m_z_n(int m) {
        ArrayList<Estate> al = new ArrayList<Estate>();
        al.addAll(this.katalogOfert);

        if (al.size() > 185) {
            EstateRadixSort.EstateRadixSort(al);
        } else {
            Collections.sort((List) al);
        }

        int rozmiar = al.size();
        if (rozmiar > 3) {
            ArrayList<Estate> al2 = new ArrayList<Estate>();
            for(int i=0; i<3; i++){
                al2.add(al.get(i));
            }
            return al2;
            /*for (int i = 3; i < rozmiar; i++) {

                al.remove(al.get(3));
            }*/
        }
        return al;
    }

    public ArrayList<Estate> wyszukaj(HashMap<String, Object> wz) {
        FabrykaAbstrakcyjna f = new FabrykaStandard();
        Estate wzorzec = f.stworzOferte(wz);
        return wyszukaj(wzorzec);
    }

    public ArrayList<Estate> wyszukaj(Estate wzorzec) {
        ArrayList<Estate> wynik = new ArrayList<Estate>();
        for (Estate tmp : katalogOfert) {
            if (tmp.matchesQuery(wzorzec)) {
                wynik.add(tmp);
            }
        }
        return wynik;
    }

    public ArrayList<Estate> zestawOferty(HashMap<String, Object> wz) {
        FabrykaAbstrakcyjna f = new FabrykaStandard();
        Estate wzorzec = f.stworzOferte(wz);
        if (katalogOfert == null) {
            katalogOfert = wyszukaj(wzorzec);
        }
        return wyszukaj_m_z_n(wz.size() / 15);
    }

    public User Szukaj_user(String nip) {
        HashMap<String, Object> hm = new HashMap<String, Object>();
        hm.put("nip", nip);
        UsersFactory uf = new UsersFactory();
        User temp = uf.createUserTemplate(hm);
        int idx;
        if ((idx = katalogUsers.indexOf(temp)) != -1) {
            return katalogUsers.get(idx);
        }
        return null;
    }

    public User stworzUsera(HashMap<String, Object> hm) {
        UsersFactory uf = new UsersFactory();
        User user = uf.createUser(hm);
        if (Szukaj_user(user.getNIP()) == null) {
            katalogUsers.add(user);
            return user;
        }
        return null;
    }

  public Estate Szukaj_estate(String numer) {
    int nr = Integer.parseInt(numer);
    return Szukaj_estate(nr);
  }

  public Estate Szukaj_estate(Estate pom) {
    //HashMap<String, Object> hm = new HashMap<String, Object>();
    //hm.put("numer_oferty", (Integer) numer_oferty);
    //FabrykaStandard fabryka = new FabrykaStandard();
    //Estate temp = fabryka.stworzWzorzecOferty(hm);
    int idx;
    if ((idx = katalogOfert.indexOf(pom)) != -1) {
      return katalogOfert.get(idx);
    }
    return null;
  }


  public Estate Szukaj_estate(int numer_oferty) {
    HashMap<String, Object> hm = new HashMap<String, Object>();
    hm.put("numer_oferty", (Integer) numer_oferty);
    FabrykaStandard fabryka = new FabrykaStandard();
    Estate temp = fabryka.stworzWzorzecOferty(hm);
    return Szukaj_estate(temp);
  }
    public Estate Dodajoferte(HashMap<String, Object> hm1, HashMap<String, Object> hm2) {
        FabrykaStandard instance1 = new FabrykaStandard();
        hm1.put("numer_oferty", (Integer) katalogOfert.size());
        Estate estate = instance1.stworzOferte(hm1);
        UsersFactory instance2 = new UsersFactory();
        User user = instance2.createUser(hm2);
        User found;
        if ((found = Szukaj_user(user.getNIP())) != null && Szukaj_estate(estate.getNumer_oferty()) == null) {
            estate.setUser(found);
            katalogOfert.add(estate);
            if (found.getEstates() == null) {
                List<Estate> estates = new ArrayList<Estate>();
                estates.add(estate);
                found.setEstates(estates);

                //found.getEstates().add(estate);
                 
                return estate;
            }
            else {
                found.getEstates().add(estate);
            }
        }
        return null;
    }

  public boolean dodajDoObserwowanych(String nr_oferty, String nip_usera){
    Estate estate = Szukaj_estate(nr_oferty);
    User zglaszajacy = Szukaj_user(nip_usera);
    if(zglaszajacy == null || estate == null)return false;
    
    return zglaszajacy.dodajDoObserwowanych(estate);

  }

  public boolean usunZobserwowanych(String nr_oferty, String nip_usera){
    Estate estate = Szukaj_estate(nr_oferty);
    User zglaszajacy = Szukaj_user(nip_usera);
    if(zglaszajacy == null || estate == null)return false;
    
    return zglaszajacy.usunZObserwowanych(estate);

  }
    public List<Comment> getKomentarze() {
        return this.komentarze;
    }

    /**
     * @param comment - obiekt komentarza wyszukany w application beanie
     */
    public void acceptComment(Comment comment) {
        comment.setAccepted(true);
    }

    /**
     * @param comment - obiekt komentarza wyszukany w application beanie
     * @param cause - powod usuniecia komentarza
     */
    public void deleteComment(Comment comment, String cause) {
        comment.setCause(cause);
        comment.setDeleted(true);
    }


	/**
	 * Podanie danych dotyczących ocen nie jest wymagane, zostana wtedy ustawione wartosci domyslne
	 * @param commentData - dane komentarza,<br /> - "title" -> tytul,<br /> - "content" -> tresc,<br /> - "nip" -> nip uzytkownika,<br /> - "numer_oferty" -> numer oferty,<br /> - "ocenaKomfort" -> ocena komfortu,<br /> - "ocenaLokalizacja" -> ocena lokalizacji,<br /> - "ocenaEstetyka" -> ocena estetyki
	 * @return stworzony komentarz lub null jesli nie można dodac
	 */
    public Comment Dodajkomentarz(HashMap<String, Object> commentData) {
        Estate estate = Szukaj_estate((Integer)commentData.get("numer_oferty"));
        User user = Szukaj_user(commentData.get("nip").toString());

		Comment comment = estate.addComment(commentData, user);

        if (comment != null) {
            komentarze.add(comment);
            return comment;
        }
        return null;
    }

    public List<Comment> getEstatesComments(String numerOferty) {
        return getEstatesComments(Szukaj_estate(numerOferty));
    }

    public List<Comment> getEstatesComments(Estate estate) {
        return estate.getComments();
    }

    public List<Comment> getUsersComments(User user) {
        List<Comment> comments = user.getComments();
        return comments;
    }

    public Comment getComment(Long commentId) {
        Iterator<Comment> iter = komentarze.iterator();
        Comment comment = null;
        while (iter.hasNext()) {
            comment = iter.next();
            if (comment.getId().equals(commentId)) {
                return comment;
            }
        }

        return null;
    }

    public List<Estate> getOferty() {
        return katalogOfert;
    }

    public List<User> getUzytkownicy() {
        return katalogUsers;
    }

    public ArrayList<Estate> getOfertyUzytkownika(String id_uz) {
        ArrayList<Estate> ar = new ArrayList();
        for (Estate e : katalogOfert) {
            if (e.getUser().getNIP().equals(id_uz)) {
                ar.add(e);
            }
        }

        return ar;
    }

    public List<Estate> getObserwowaneUzytkownika(String id_uz) {
        List<Estate> ar = this.Szukaj_user(id_uz).getObserwowane();
        return ar;
    }
    
    public HashMap<String, String> srednieOceny(String estate_id)
    {
    	Estate oferta = Szukaj_estate(Integer.parseInt(estate_id));
    	return oferta.obliczSrednieOceny();
    }
    
    /*
    public int dodajDoObserwowanych(String nr_oferty, String nip_usera){
        int num = Integer.parseInt(nr_oferty);
        Estate estate = Szukaj_estate(num);
        User zglaszajacy = Szukaj_user(nip_usera);
        for(Estate e : zglaszajacy.getObserwowane()){
            if(e.getNumer_oferty() == num)return ErrorCodes.OBS_ALREADYEXISTS;
        }
        zglaszajacy.getObserwowane().add(estate);
        return ErrorCodes.OBS_OK;
    }

    public int usunZobserwowanych(String nr_oferty, String nip_usera){
        int num = Integer.parseInt(nr_oferty);
        User zglaszajacy = Szukaj_user(nip_usera);
        ListIterator<Estate> it = zglaszajacy.getObserwowane().listIterator();
        while(it.hasNext()){
            if(it.next().getNumer_oferty() == num){
                it.remove();
                return ErrorCodes.OBS_OK;
            }
        }
        return ErrorCodes.OBS_NOTFOUND;
    }*/

    public boolean zglosZainteresowanie(String nipZglaszajacego, String nipWlasciciela, String nr_oferty, String smtp, String isp_smtp,
    String appMail) throws MessagingException{
        Estate estate = Szukaj_estate(Integer.parseInt(nr_oferty));
        User zglaszajacy = Szukaj_user(nipZglaszajacego);
        User wlasciciel = Szukaj_user(nipWlasciciela);
        String zglaszajacy_m = zglaszajacy.getMail();
        String wlasciciel_m =  wlasciciel.getMail();

        estate.setInterestedUser(zglaszajacy);

        boolean debug = false;

        Properties props = new Properties();
        props.put(smtp, isp_smtp);

        Session session = Session.getDefaultInstance(props, null);
        session.setDebug(debug);

        Message msg = new MimeMessage(session);

        InternetAddress addressFrom = new InternetAddress(appMail);
        msg.setFrom(addressFrom);

        InternetAddress[] addressTo = new InternetAddress[2];

        addressTo[0] = new InternetAddress(zglaszajacy_m);
        addressTo[1] = new InternetAddress(wlasciciel_m);

        msg.setRecipients(Message.RecipientType.TO, addressTo);


        msg.setSubject("Zgłoszenie zainteresowania nieruchomością.");
        String tekst = "Nasz serwis odnotował zgłoszenie zainteresowania użytkownika "+zglaszajacy.getLogin()+
        "nieruchomością o numerze ewidencyjnym " + estate.getId() + "wystawioną przez użytkownika " +
        wlasciciel.getLogin() + "\n";
        tekst+= "E-mail zainteresowanego: " + zglaszajacy_m + "\n";
        tekst+= "Telefon zainteresowanego: " + zglaszajacy.getPhone() + "\n";
        tekst+= "E-mail właściciela nieruchomości: " + wlasciciel_m + "\n";
        tekst+= "Telefon właściciela nieruchomości: " + wlasciciel.getPhone() + "\n";
        msg.setContent(tekst, "text/plain");
        Transport.send(msg);

        return true;
    }



  public boolean usunOferte(HashMap<String, Object> hm1, HashMap<String, Object> hm2) {
    FabrykaStandard instance1 = new FabrykaStandard();
    hm1.put("numer_oferty", (Integer) katalogOfert.size());
    Estate estate = instance1.stworzOferte(hm1);
    UsersFactory instance2 = new UsersFactory();
    User user = instance2.createUser(hm2);
    User found;

    if ((found = Szukaj_user(user.getNIP())) == null)return false;
      estate.setUser(found);
     // if (Szukaj_estate(estate) != null) {
    return  katalogOfert.remove(estate);

       /* return true;
      }
    }
    return false;*/
  }

  public boolean edytujOferte(HashMap<String, Object> hm1, HashMap<String, Object> hm2, HashMap<String, Object> nowa) {
    FabrykaStandard instance1 = new FabrykaStandard();
    hm1.put("numer_oferty", (Integer) katalogOfert.size());
    Estate estate = instance1.stworzOferte(hm1);
   // Estate nowy = instance1.stworzOferte(nowa);
  //  UsersFactory instance2 = new UsersFactory();
  //  User user = instance2.createUser(hm2);
   // User found;
  //  if ((found = Szukaj_user(user.getNIP())) != null) {
      //estate.setUser(found);
    //  nowy.setUser(found);
    Estate znal=Szukaj_estate(estate);
      if (znal!= null ) {
          znal.update(nowa);
       return true;
      }

    return false;
  }
}
